package Client;

import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.net.*;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

// Client class to let a user play Tic-Tac-Toe with
// another user across a network.
public class DynamicObjectsHandler extends JPanel {

	private EaTGClient parent = null;

	public DynamicObjectsHandler(EaTGClient t) {
		parent = t;
	}

	long fpsCalc = 0;
	int fpsUpdates = 0;
	int fFpsUpdates = 0;
	boolean movePlayerX = true;
	boolean movePlayerY = true;

	public void drawSee(Graphics g, Point start) {
		int torch_power = 150;
		int torch_step = 120;
		int torch_angle = 60;
		int torch_angle_step = 20;
		// int walk_speed = 6;
		// int radius = 8;

		Point mouseloc = MouseInfo.getPointerInfo().getLocation();
		mouseloc = new Point(parent.mouseX, parent.mouseY);

		double angle = getAngle(start, mouseloc);

		parent.me.setAngle(angle);

		g.setColor(Color.red);

		g.drawLine(start.x, start.y, mouseloc.x, mouseloc.y);

		Point lastLine = start;

		for (int x = 0; x <= torch_angle; x += (torch_angle / torch_angle_step)) {
			double ray_angle = angle / (Math.PI / 180) - (torch_angle / 2) + x;
			ray_angle = ray_angle * (Math.PI / 180);

			long degrees = Math.round(angle / (Math.PI / 180));
			if (degrees < 0) {
				degrees += 360;
			}

			// System.out.println("ray likes " + ray_angle);
			int y;
			for (y = 1; y <= torch_step; y++) {
				/*
				 * if
				 * (environment.hitTest(this._x+(torch_power/torch_step*y)*Math
				 * .cos(ray_angle),
				 * this._y+(torch_power/torch_step*y)*Math.sin(ray_angle),
				 * true)) { break; }
				 */
				// if (hitBounds(new
				// Point(Math.round(Math.round(start.x+(torch_power/torch_step*y)*Math.cos(ray_angle))),
				// Math.round(Math.round(start.y+(torch_power/torch_step*y)*Math.sin(ray_angle))))))
				// {
				// break;
				// }
			}
			int nextPointX = Math.round(Math.round(start.x
					+ (torch_power / torch_step * y) * Math.cos(ray_angle)));
			// nextPointX = (int) ((int)
			// start.x+(torch_power/torch_step*y)*Math.cos(degrees));
			int nextPointY = Math.round(Math.round(start.y
					+ (torch_power / torch_step * y) * Math.sin(ray_angle)));
			g.drawLine(lastLine.x, lastLine.y, nextPointX, nextPointY);
			lastLine = new Point(nextPointX, nextPointY);
			// light.lineTo(this._x+(torch_power/torch_step*y)*Math.cos(ray_angle),
			// this._y+(torch_power/torch_step*y)*Math.sin(ray_angle));
		}
		g.drawLine(lastLine.x, lastLine.y, start.x, start.y);
	}

	protected void paintComponent(Graphics g3) {
		if (parent.screen != null) {
			Graphics g = parent.screen.getGraphics();
			/*
			 * for (int i = 0; i < parent.th.tilesCount; i++) { Point p =
			 * parent.th.tilePoints.get(i);
			 * g.drawImage(parent.th.tilesPaint.get(i), p.x, p.y, null); }
			 */
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (fpsCalc == 0 || fpsCalc < System.currentTimeMillis() - 1000) {
				fFpsUpdates = fpsUpdates;
				fpsCalc = System.currentTimeMillis();
				fpsUpdates = 0;
			}

			g2.setPaint(Color.red);
			try {
				for (Player p : parent.players) {
					if (p.getDestroy()) {
						parent.players.remove(p);
						continue;
					}
					Point loc = p.getScreenLoc();
					loc = new Point(loc.x + parent.th.mapStart.x, loc.y + parent.th.mapStart.y);
					g2.fill(new Ellipse2D.Double(loc.x, loc.y, 4, 4));
					g2.drawString(showAsName(p, true), loc.x, loc.y);
				}
			} catch (ConcurrentModificationException e) {
			}
			g2.drawString("Location: " + parent.me.getAbsoluteLoc().x + ", "
					+ parent.me.getAbsoluteLoc().y, 10, 240);
			g2.drawString("Map Start: " + parent.th.mapStart.x + ", "
					+ parent.th.mapStart.y, 10, 220);
			g2.drawString(parent.players.size() + 1 /* you count */
					+ " players online", 10, 200);
			g.drawString("FPS: " + fFpsUpdates, 10, 180);
			g.drawString("Ammo: " + parent.ammolist.size(), 10, 160);
			g2.setPaint(Color.blue);
			Player you = parent.me;
			if (you != null) {
				Point loc = you.getAbsoluteLoc();
				if (movePlayerX)
					loc.x = parent.th.windowWidth / 2;
				if (movePlayerY)
					loc.y = parent.th.windowHeight / 2;
				g2.fill(new Ellipse2D.Double(loc.x, loc.y, 4, 4));
				g2.drawString(showAsName(you, false), loc.x, loc.y);

				drawSee(g, loc);
			}

			g.setColor(Color.black);
			for (Ammo a : parent.ammolist) {
				double bx = a.getStartLoc().x + a.getSpeed()
						* Math.cos(a.getAngle());
				double by = a.getStartLoc().y + a.getSpeed()
						* Math.sin(a.getAngle());

				g2.fill(new Ellipse2D.Double(bx, by, 4, 4));
			}

			fpsUpdates++;
			g3.drawImage(parent.screen, 0, 0, parent.screen.getWidth(),
					parent.screen.getHeight(), null);
			/*
			 * parent.screen.getGraphics().clearRect(0, 0,
			 * parent.th.windowWidth, parent.th.windowHeight);
			 * parent.screen.flush();
			 */
			parent.screen = new BufferedImage(parent.th.windowWidth,
					parent.th.windowHeight, BufferedImage.TYPE_INT_ARGB);
		}
	}

	private String showAsName(Player p, boolean showPing) {
		return p.getName()
				+ (showPing && p.getLatency() != -1 ? " [" + p.getLatency()
						+ "]" : "");
	}

	private double getAngle(Point loc, Point mouseloc) {
		// int dist_x = mouseloc.x - loc.x;
		// int dist_y = mouseloc.y - loc.y;
		// double angle = Math.atan2(dist_y, dist_x);
		double angle = Math.atan2(mouseloc.y - loc.y, mouseloc.x - loc.x);
		long degrees = Math.round(angle / (Math.PI / 180));
		if (degrees < 0) {
			degrees += 360;
		}
		// System.out.println("fking degrees " + degrees);
		return angle;

	}
}